#include "rhythm_light.h"
#include "cJSON.h"
#include "json_data.h"
#include "fast_conble_func.h"
#include "log.h"

#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <time.h>

cJSON *rhythm_Json = NULL; // msg键，判断类型使用
// 节律json中的重要节点指针
cJSON *rhythm_rootJson = NULL;
cJSON *rhythm_dataJson = NULL;
cJSON *rhythm_rhyJson = NULL;
cJSON *rhythm_rECJson = NULL;
cJSON *rhythm_rhyRJson = NULL; // 节律关系
cJSON *rhythm_rNJson = NULL;

uint32_t *rhythm_timer = NULL;
// rthythm_light_t *rthythm_light = NULL;
rN_t *rN = NULL; // 数组形式

// 节律json中的必要信息
uint8_t rEC = 0;         // 节律周期
uint16_t ryId = 0;       // 节律ID
uint8_t *rhyN = NULL;    // 节律名称
uint16_t ryct = 0;       // 节律总数
uint16_t ryct_group = 0; // 群组总数

uint16_t node_num = 0;        // 当前时间的节点数，对应节点数组的前一个，+1为后一个
uint8_t executeOnceFlag = 0;  // 只执行一次的标志
uint8_t executeOnceEnd = 0;   // 只执行一次的标志
uint32_t executeOnceTime = 0; // 执行一次的时间

// 周期时间
int32_t lasttimeSecondes = -1; // 保存上一次的周期时间
int32_t nowtimeSeconds = 0;

uint8_t controlGroupFlag = 0; // 群组控制标志，在节律照明时需要
/**
 * @description: 获取今天星期几,0 表示星期日，1 表示星期一
 * @return {*}
 */
uint8_t getWeek()
{
    time_t t = time(NULL);
    struct tm *local_time = localtime(&t);
    if (local_time == NULL)
    {
        perror("获取本地时间失败");
        return 7;
    }

    int day_of_week = local_time->tm_wday;
    return day_of_week;
}

/**
 * @description: 二进制字符串转数字
 * @return {*}
 */
int get_rEC()
{
    if (rhythm_rECJson != NULL)
    {
        uint8_t *p = rhythm_rECJson->valuestring;
        rEC = 0; // 清空
        for (int i = 0; i < 8; i++)
        {
            rEC = (rEC << 1) | (p[i] - '0'); // 二进制字符串转数字
        }
    }
    if (rEC & 0x80) // 只执行一次时的记录
    {
        executeOnceFlag = 1;
        executeOnceEnd = 0;
        executeOnceTime = nowtime_seconds();
    }
    else
    {
        executeOnceFlag = 0;
    }
    return 0;
}

/**
 * @description: 获取参数json，只执行一次获取一次参数
 * @return {*}
 */
int get_paramJson()
{
    int ret = 0;
    cJSON *tempJson = NULL;
    if (rhyN != NULL) // 先释放内存
    {
        free(rhyN);
    }

    lasttimeSecondes = -1; // 初始化
    rhythm_dataJson = cJSON_GetObjectItemCaseSensitive(rhythm_rootJson, "data");
    if (rhythm_dataJson == NULL)
    {
        return -1;
    }
    rhythm_rhyJson = cJSON_GetObjectItemCaseSensitive(rhythm_dataJson, "rhy");
    if (rhythm_rhyJson == NULL)
    {
        return -1;
    }
    rhythm_rECJson = cJSON_GetObjectItemCaseSensitive(rhythm_rhyJson, "rEC");
    if (rhythm_rECJson == NULL)
    {
        return -1;
    }
    rhythm_rNJson = cJSON_GetObjectItemCaseSensitive(rhythm_rhyJson, "rN");
    if (rhythm_rNJson == NULL)
    {
        return -1;
    }
    tempJson = cJSON_GetObjectItemCaseSensitive(rhythm_rhyJson, "rhyN");
    if (tempJson == NULL)
    {
        return -1;
    }
    rhyN = strdup_custom(tempJson->valuestring);
    ret = get_rEC();
    if (ret != 0)
    {
        return -1;
    }
    ret = get_ryct();
    if (ret != 0)
    {
        return -1;
    }
    ret = rN_parse();
    // printf("parse:%d\n", ryct_group);
    if (ret != 0)
    {
        rN_free();
        return -1;
    }
    printf("03\n");
}

/**
 * @description: 获取节律时间
 * @return {*}
 */
uint8_t get_time()
{
    if (rhythm_timer != NULL)
    {
        free(rhythm_timer);
    }
    rhythm_timer = (uint32_t *)malloc(ryct * sizeof(uint32_t));
    if (cJSON_IsArray(rhythm_rNJson))
    {
        int array_size = cJSON_GetArraySize(rhythm_rNJson);
        for (int i = 0; i < array_size; i++)
        {
            cJSON *item = cJSON_GetArrayItem(rhythm_rNJson, i);
            cJSON *timeJson = cJSON_GetObjectItemCaseSensitive(item, "nT");
            rhythm_timer[i] = time_to_seconds(timeJson->valuestring);
            // printf("%s\n", timeJson->valuestring);
            printf("%d\n", rhythm_timer[i]);
        }
    }
}

// 获取节律总数
int get_ryct()
{
    if (rhythm_rhyJson != NULL)
    {
        cJSON *tempJson = cJSON_GetObjectItemCaseSensitive(rhythm_rhyJson, "ryct");
        if (tempJson == NULL)
        {
            return ERROR_NOT_ID;
        }
        else
        {
            ryct = tempJson->valueint;
        }
    }
    return ERROR_NONE;
}

// 获取节点时间 nT, 一天中的各个节点时间
uint8_t get_light()
{
    // if (rthythm_light != NULL)
    // {
    //     free(rthythm_light);
    // }
    // rthythm_light = (rthythm_light_t *)malloc(ryct * sizeof(rthythm_light));
    if (cJSON_IsArray(rhythm_rhyRJson))
    {
        int array_size = cJSON_GetArraySize(rhythm_rhyRJson);
        for (int i = 0; i < array_size; i++)
        {
            cJSON *item = cJSON_GetArrayItem(rhythm_rhyRJson, i);
            cJSON *timeJson = cJSON_GetObjectItemCaseSensitive(item, "nT");
            rhythm_timer[i] = time_to_seconds(timeJson->valuestring);
            // printf("%s\n", timeJson->valuestring);
            printf("%d\n", rhythm_timer[i]);
        }
    }
}

// 时间字符串转为秒计数
uint32_t time_to_seconds(const char *time_str)
{
    uint32_t hours, minutes, seconds;
    if (sscanf(time_str, "%d:%d:%d", &hours, &minutes, &seconds) != 3)
    {
        fprintf(stderr, "无效的时间格式\n");
        return -1;
    }

    return hours * 3600 + minutes * 60 + seconds;
}

// 获取当前时间的秒计数
uint32_t nowtime_seconds()
{
    time_t now = time(NULL);              // 获取当前时间的时间戳
    struct tm *tm_info = localtime(&now); // 将时间戳转换为本地时间结构体

    uint32_t seconds = tm_info->tm_hour * 3600 + tm_info->tm_min * 60 + tm_info->tm_sec; // 计算当前时间的秒数
    return seconds;
}

// 释放rN节律节点内存
void rN_free()
{
    if (rN != NULL) // 释放内存
    {
        if (rN->nN != NULL)
        {
            free(rN->nN);
        }
        if (rN->rhyR != NULL)
        {
            free(rN->rhyR);
        }
        if (rN != NULL)
        {
            free(rN);
        }
    }
}

// 节律节点解析
int rN_parse()
{
    int ret = 0;

    rN_free();
    rN = (rN_t *)malloc(ryct * sizeof(rN_t));
    memset(rN, 0, ryct * sizeof(rN_t));

    if (cJSON_GetArraySize(rhythm_rNJson) != ryct) // 节点数与节点数组大小不对应
    {
        return -1;
    }
    for (int i = 0; i < ryct; i++)
    {
        cJSON *tempJson = NULL;
        cJSON *item = NULL;
        rN_t *rN_current = NULL;
        rN_current = rN + i;
        item = cJSON_GetArrayItem(rhythm_rNJson, i);
        tempJson = cJSON_GetObjectItemCaseSensitive(item, "nId");
        if (tempJson == NULL)
        {
            return ERROR_NOT_ID;
        }
        else
        {
            rN_current->nId = tempJson->valueint;
        }
        tempJson = cJSON_GetObjectItemCaseSensitive(item, "nT");
        if (tempJson == NULL)
        {
            return ERROR_NOT_ID;
        }
        else
        {
            rN_current->nT = time_to_seconds(tempJson->valuestring);
        }
        tempJson = cJSON_GetObjectItemCaseSensitive(item, "nN");
        if (tempJson == NULL)
        {
            return ERROR_NOT_ID;
        }
        else
        {
            rN_current->nN = strdup_custom(tempJson->valuestring);
        }

        tempJson = cJSON_GetObjectItemCaseSensitive(item, "rhyR"); // 数组
        int array_size = cJSON_GetArraySize(tempJson);
        ryct_group = array_size; // 每个节点下的群组数量
        rN_current->rhyR_size = array_size;
        rN_current->rhyR = (rhyR_t *)malloc(array_size * sizeof(rhyR_t));
        memset(rN_current->rhyR, 0, array_size * sizeof(rhyR_t));
        for (int j = 0; j < array_size; j++) // 每个节点下的多个群组
        {
            cJSON *temp1Json = NULL;
            cJSON *item1 = NULL;
            rhyR_t *rhyRJson_current = rN_current->rhyR + j;
            item1 = cJSON_GetArrayItem(tempJson, j);

            temp1Json = cJSON_GetObjectItemCaseSensitive(item1, "reId");
            if (temp1Json == NULL)
            {
                return ERROR_NOT_ID;
            }
            else
            {
                rhyRJson_current->reId = temp1Json->valueint;
            }
            temp1Json = cJSON_GetObjectItemCaseSensitive(item1, "gid");
            if (temp1Json == NULL)
            {
                return ERROR_NOT_ID;
            }
            else
            {
                rhyRJson_current->gid = temp1Json->valueint;
            }
            temp1Json = cJSON_GetObjectItemCaseSensitive(item1, "type");
            if (temp1Json == NULL)
            {
                return ERROR_NOT_ID;
            }
            else
            {
                rhyRJson_current->type = temp1Json->valueint;
            }
            cJSON *gEPJson = NULL;
            gEPJson = cJSON_GetObjectItemCaseSensitive(item1, "gEP");
            temp1Json = cJSON_GetObjectItemCaseSensitive(gEPJson, "pwr");
            if (temp1Json == NULL)
            {
                return ERROR_NOT_ID;
            }
            else
            {
                rhyRJson_current->gEP.pwr = temp1Json->valueint;
            }
            temp1Json = cJSON_GetObjectItemCaseSensitive(gEPJson, "r");
            if (temp1Json == NULL)
            {
                return ERROR_NOT_ID;
            }
            else
            {
                rhyRJson_current->gEP.r = temp1Json->valueint;
            }
            temp1Json = cJSON_GetObjectItemCaseSensitive(gEPJson, "g");
            if (temp1Json == NULL)
            {
                return ERROR_NOT_ID;
            }
            else
            {
                rhyRJson_current->gEP.g = temp1Json->valueint;
            }
            temp1Json = cJSON_GetObjectItemCaseSensitive(gEPJson, "b");
            if (temp1Json == NULL)
            {
                return ERROR_NOT_ID;
            }
            else
            {
                rhyRJson_current->gEP.b = temp1Json->valueint;
            }
            temp1Json = cJSON_GetObjectItemCaseSensitive(gEPJson, "brightness");
            if (temp1Json == NULL)
            {
                return ERROR_NOT_ID;
            }
            else
            {
                rhyRJson_current->gEP.brightness = temp1Json->valueint;
            }
            temp1Json = cJSON_GetObjectItemCaseSensitive(gEPJson, "c");
            if (temp1Json == NULL)
            {
                return ERROR_NOT_ID;
            }
            else
            {
                rhyRJson_current->gEP.c = temp1Json->valueint;
            }
            temp1Json = cJSON_GetObjectItemCaseSensitive(gEPJson, "w");
            if (temp1Json == NULL)
            {
                return ERROR_NOT_ID;
            }
            else
            {
                rhyRJson_current->gEP.w = temp1Json->valueint;
            }
        }
    }

    if (ryct >= 2) // 验证各个节点下的群组ID相同
    {
        for (int i = 0; i < ryct_group; i++)
        {
            for (int j = 1; j < ryct; j++) // 不同节点下比较
            {
                if (((rN + 0)->rhyR + i)->gid != ((rN + j)->rhyR + i)->gid)
                {
                    return -1;
                }
            }
        }
    }

    // 根据群组id，列表查找灯组类型
    // device_type获取设备类型
    uint16_t device_type = 0;
    uint8_t ch[20] = {0};
    // snprintf(ch, sizeof(ch), "%d", groupID);
    cJSON *index = NULL;
    index = cJSON_CreateObject();
    cJSON_AddStringToObject(index, "groupId", ch);
    cJSON *blecatetoryJson = NULL;
    blecatetoryJson = cJSON_CreateObject();
    cJSON_AddStringToObject(blecatetoryJson, "blecatetory", "");
    for (int i = 0; i < ryct_group; i++)
    {
        memset(ch, 0, sizeof(ch));
        snprintf(ch, sizeof(ch), "%d", ((rN + 0)->rhyR + i)->gid);
        cJSON_SetValuestring(index->child, ch);
        ret = list_getOneAttrJson(groupList_Json, index, &blecatetoryJson);
        if (ret != 0)
        {
            fprintf(stderr, "check group json failed ret:%d\n", ret);
        }
        // printf("v:%s\n", blecatetoryJson->child->valuestring);
        memset(ch, 0, sizeof(ch));
        strncpy(ch, blecatetoryJson->child->valuestring, sizeof(ch));
        if (!strcmp(ch, "CWLIGHT"))
        {
            device_type = 0x2ba8;
        }
        else if (!strcmp(ch, "RGBCWLIGHT"))
        {
            device_type = 0x2aa8;
        }
        else
        {
            device_type = 0x2ba8;
        }

        for (int j = 0; j < ryct; j++) // 不同节点下比较
        {
            ((rN + j)->rhyR + i)->deviceType = device_type;
        }
    }
    cJSON_Delete(index);
    cJSON_Delete(blecatetoryJson);

    for (int i = 0; i < ryct_group; i++)
    {
        // printf("%d\n", (rN + i)->rhyR->gEP.brightness);
        // printf("type:0x%X\n", ((rN + 0)->rhyR+i)->deviceType);
    }
    return ERROR_NONE;
}

void rN_print()
{
    rN_t *rN_current = NULL;
    for (int i = 0; i < ryct; i++)
    {
        rN_current = rN + i;
        printf("%d\t%d\t%s\n", rN_current->nId, rN_current->nT, rN_current->nN);
        for (int j = 0; j < rN_current->rhyR_size; j++)
        {
            printf("\t%d\t%d\t%d\t%d\n", (rN_current->rhyR + j)->reId, (rN_current->rhyR + j)->gid, (rN_current->rhyR + j)->type, (rN_current->rhyR + j)->gEP.pwr);
        }
    }
}

/**
 * @description: 群组任务
 * @return {*}
 */
void task_gEP()
{
    // node_num
    node_num = 0; // 时间节点,当前时间下的节点排序
    uint32_t nowtime = 0;
    double timeScale = 0.0;
    nowtime = nowtime_seconds();
    // nowtime = 28400;  //测试用

    if (ryct == 1) // 只有一个节点
    {
    }

    if (ryct >= 2)
    {
        for (int i = 0; i < ryct; i++) // 节点总数
        {
            rN_t *rN_current = rN + i;
            if (nowtime < rN_current->nT)
            {
                node_num = i; // 时间分为ryct+1段
                break;
            }
        }

        rN_t *rN_prev = NULL;
        rN_t *rN_next = rN + node_num;
        if (node_num == 0)
        {
            rN_prev = rN + ryct - 1; // 当前时间下的前后两个节点, 总数-1
        }
        else
        {
            rN_prev = rN_next - 1; // 当前时间下的前后两个节点
        }
        // printf("%d\n", rN_prev->rhyR->gEP.brightness);
        // 计算时间尺度比例
        uint32_t _nowtime = 0;
        if (nowtime < rN_prev->nT)
        {
            _nowtime = nowtime + 86400;
        }
        else
        {
            _nowtime = nowtime;
        }
        if (rN_next->nT < rN_prev->nT)
        {
            timeScale = (_nowtime - rN_prev->nT) * 1.0 / (rN_next->nT + 86400 - rN_prev->nT);
        }
        else
        {
            timeScale = (_nowtime - rN_prev->nT) * 1.0 / (rN_next->nT - rN_prev->nT);
        }

        rhyR_t *rhyR_prev = NULL;
        rhyR_t *rhyR_next = NULL;
        // 每个节点下，各个群组的执行参数
        for (int i = 0; i < ryct_group; i++)
        {
            gEP_t new_gEP = {0};
            rhyR_prev = rN_prev->rhyR + i;
            rhyR_next = rN_next->rhyR + i;

            new_gEP.r = rhyR_prev->gEP.r + timeScale * (rhyR_next->gEP.r - rhyR_prev->gEP.r);
            new_gEP.g = rhyR_prev->gEP.g + timeScale * (rhyR_next->gEP.g - rhyR_prev->gEP.g);
            new_gEP.b = rhyR_prev->gEP.b + timeScale * (rhyR_next->gEP.b - rhyR_prev->gEP.b);
            new_gEP.brightness = rhyR_prev->gEP.brightness + timeScale * (rhyR_next->gEP.brightness - rhyR_prev->gEP.brightness);
            new_gEP.c = rhyR_prev->gEP.c + timeScale * (rhyR_next->gEP.c - rhyR_prev->gEP.c);
            new_gEP.w = rhyR_prev->gEP.w + timeScale * (rhyR_next->gEP.w - rhyR_prev->gEP.w);

            // if (i == 0)
            // {
            //     printf("gEP:%d\t%d\t%d\n", rhyR_prev->gEP.brightness, rhyR_prev->gEP.c, rhyR_prev->gEP.w);
            //     printf("gEP:%d\t%d\t%d\n", rhyR_next->gEP.brightness, rhyR_next->gEP.c, rhyR_next->gEP.w);
            //     printf("gEP:%d\t%d\t%d\n", new_gEP.brightness, new_gEP.c, new_gEP.w);
            // }
            log_info("rhythm_groupControl i:%d, type:0x%X, gid:%d\n", i, rhyR_prev->deviceType, rhyR_prev->gid);
            for (int k = 0; k < 5; k++)
            {
                rhythm_groupControl(rhyR_prev->gid, rhyR_prev->deviceType, rhyR_prev->gEP);
                struct timespec req = {0, 200 * 1000000};
                nanosleep(&req, NULL);
                if (controlGroupFlag == 0)
                {
                    printf("ack\n");
                    break;
                }
            }
        }
        printf("%d\t%d\t%d\n", rN_prev->nT, nowtime, rN_next->nT);
        // printf("%d\n", rN_prev->nId);
        // printf("d:%f\n", timeScale);
    }
}

// 周期任务，返回0执行，返回非0不执行节律
// 返回0执行节律，返回-1不执行节律（关灯后不再执行），返回-2关闭灯光（关灯后0时后第一个循环）
int task_rEC(void)
{
    int ret = 0;
    uint8_t todayDoFlag = 0;  // 今天执行标志
    uint8_t crossDayFlag = 0; // 跨天标志
    nowtimeSeconds = nowtime_seconds();

    if (lasttimeSecondes == -1) // 程序第一次执行
    {
        // return 0; // 执行节律
        lasttimeSecondes = nowtimeSeconds;
    } // 返回

    if (nowtimeSeconds < lasttimeSecondes) // 过了0点
    {
        crossDayFlag = 1;
    }
    else
    {
        crossDayFlag = 0;
    } // 判断过0点

    if (rEC & 0x80) // 这代码可在解析json时执行
    {
        executeOnceFlag = 1;
    }
    if (executeOnceFlag) // 只执行一次的
    {
        if (crossDayFlag)
        {
            executeOnceEnd = 1;
        }
        // rEC为8位变量，bit7为只执行一次，bit6-0对应一周
        if (executeOnceEnd) // 单次执行结束
        {
            if (crossDayFlag)
            {
                ret = -2; // 执行一次关灯
            }
            else
            {
                ret = -1; // 不执行
            }
        }
        else
        {
            ret = 0;
        }
    }
    else // 按周执行
    {
        todayDoFlag = 0;
        switch (getWeek())
        {
        case 0: // 周日
            if (rEC & 0x01)
                todayDoFlag = 1;
            break;
        case 1: // 周一
            if (rEC & 0x40)
                todayDoFlag = 1;
            break;
        case 2: // 周二
            if (rEC & 0x20)
                todayDoFlag = 1;
            break;
        case 3: // 周三
            if (rEC & 0x10)
                todayDoFlag = 1;
            break;
        case 4: // 周四
            if (rEC & 0x08)
                todayDoFlag = 1;
            break;
        case 5: // 周五
            if (rEC & 0x04)
                todayDoFlag = 1;
            break;
        case 6: // 周六
            if (rEC & 0x02)
                todayDoFlag = 1;
            break;
        default:
            break;
        }
        if (todayDoFlag) // 当天执行
        {
            ret = 0;
        }
        else // 当天不执行
        {
            if (crossDayFlag)
            {
                ret = -2; // 执行一次关灯
            }
            else
            {
                ret = -1; // 不执行
            }
        }
    }
    lasttimeSecondes = nowtimeSeconds;
    return ret;
}

void readData(void)
{
    int ret = 0;
    int fileSize = 0;
    FILE *file = fopen("rhythm_data_test.json", "r");
    if (file == NULL)
    {
        printf("Failed to open file.\n");
        return;
    }
    // 获取文件大小
    fseek(file, 0, SEEK_END);
    fileSize = ftell(file);
    fseek(file, 0, SEEK_SET);
    // 分配足够大的内存来存储文件内容
    char *buffer = (char *)malloc(fileSize + 1);
    if (buffer == NULL)
    {
        perror("内存分配失败");
        fclose(file);
    }
    // 读取文件内容到内存中
    if (fread(buffer, 1, fileSize, file) != fileSize)
    {
        perror("读取文件时出错");
        free(buffer);
        fclose(file);
    }
    buffer[fileSize] = '\0'; // 添加字符串结束符
    fclose(file);
    // rhythm_rootJson = cJSON_Parse(buffer);
    ret = read_rhythmData(buffer);
    free(buffer);
    printf("%d\n", ret);

    // ret = get_paramJson();
    // if (ret == -1)
    // {
    //     printf("get parameter error\n");
    // }
    // printf("%s\n", rhythm_rECJson->valuestring);
    // printf("%s\n", rhyN);
    // printf("%d\n", ryct);
    // printf("group:%d\n", ryct_group);
    // get_time();
    // printf("%d\n", ret);
    // printf("sec:%d\n", nowtime_seconds());
    // task_gEP();
    // printf("%d\n", node_num);
    // rN_print();
    // printf("%s\n", cJSON_Print(rhythm_rNJson));
    // printf("parse:%d\n", ryct_group);
    // rhythm_timer_create();
    // rhythm_timer_set(); // 启动定时任务

#if 0 // 用于测试星期运行
    rEC = 0b01000000;
    int count = 10;
    while (count--)
    {
        ret = task_rEC();
        printf("%d\n", ret);
        sleep(5);
    }
#endif
}

int read_rhythmData(char *buffer)
{
    int ret = 0;
    // log_info("received buffer:%s\n", buffer);
    rhythm_Json = cJSON_Parse(buffer);
    if (rhythm_Json == NULL) // 无效json
    {
        fprintf(stderr, "rhythm json null\n");
        return -1;
    }
    cJSON *msgJson = cJSON_GetObjectItemCaseSensitive(rhythm_Json, "msg");
    if (msgJson == NULL) // 无效json
    {
        fprintf(stderr, "rhythm json msg null\n");
        return -1;
    }
    if (!strcmp(msgJson->valuestring, "start"))
    {
        if (rhythm_rootJson != NULL)
        {
            rhythm_timer_set(); // 开始执行
            return 0;
        }
        else
        {
            fprintf(stderr, "rhythm json start null\n");
            return -1;
        }
    }
    else if (!strcmp(msgJson->valuestring, "stop"))
    {
        rhythm_stop(); // 结束
        return 0;
    }
    else if (!strcmp(msgJson->valuestring, "success")) // 执行解析数据
    {
        if (rhythm_rootJson != NULL)
        {
            cJSON_Delete(rhythm_rootJson);
        }
        rhythm_rootJson = cJSON_Duplicate(rhythm_Json, 1);
        cJSON_Delete(rhythm_Json);
    }

    if (rhythm_rootJson == NULL)
    {
        fprintf(stderr, "rhythm json parse failed\n");
        return -1;
    }
    ret = get_paramJson();
    if (ret == -1)
    {
        fprintf(stderr, "get parameter error\n");
        return -1;
    }
    log_info("节律数据解析完成");
    rhythm_timer_set();
    return 0;
}

/**
 * @description: 节律照明的群组控制
 * @param {uint16_t} groupID 群组ID
 * @param {gEP_t} ep 照明参数
 * @return {*}
 */
int rhythm_groupControl(uint16_t groupID, uint16_t deviceType, gEP_t ep)
{
    int ret = 0;
    uint8_t controlData[6] = {0};

    controlData[0] = ep.brightness;
    if (ep.pwr)
    {
        controlData[0] |= 0x80;
        controlData[1] = ep.b;
        controlData[2] = ep.r;
        controlData[3] = ep.g;
        controlData[4] = ep.w;
        controlData[5] = ep.c;

        // for (int i = 0; i < 3; i++)
        {
            ret = FastConbleGroupControl(groupID, deviceType, controlData, 6);
        }

        // log_info("group control %X\n", controlData[0]);
        for (int i = 0; i < 6; i++)
        {
            printf("%X\t", controlData[i]);
        }
        printf("\n");
    }
    else
    {
        controlData[0] = 0;
        ret = FastConbleGroupControl(groupID, deviceType, controlData, 1);
    }
    return ret;
}

/**
 * @description: 关闭节律照明中的所有群组
 * @return {*}
 */
int rhythm_groupOff()
{
    int ret = 0;
    uint8_t controlData[1] = {0};
    rhyR_t *rhyR0 = (rN + 0)->rhyR;
    cJSON *config = NULL;
    config = cJSON_CreateArray();
    cJSON *_configObject = NULL;
    _configObject = cJSON_CreateObject();
    cJSON_AddStringToObject(_configObject, "CF_OnOff", "0");
    cJSON_AddItemToArray(config, _configObject);
    for (int i = 0; i < ryct_group; i++) // 群组数
    {
        // ret = FastConbleGroupControl((rhyR0 + i)->gid, 0x2ba8, controlData, 1);
        for (int j = 0; j < 5; j++)
        {
            ret = controlGroupJson((rhyR0 + i)->gid, config);
            struct timespec req = {0, 200 * 1000000};
            nanosleep(&req, NULL);
            if (controlGroupFlag == 0)
            {
                printf("ack\n");
                break;
            }
        }
    }
    cJSON_Delete(config);
    return 0;
}

#define CLOCKID CLOCK_REALTIME
#define SIG SIGRTMIN

// Linux定时器使用同一个定时中断函数，使用
// si->si_value.sival_int字段将包含对应的定时器编号
void UrlRequest_timer_handler();
void rhythm_timer_handler();
void timer_handler(int sig, siginfo_t *si, void *uc)
{
    int ret = 0;
    int timer_irq = 0;
    printf("Timer expired at %ld\n", (long)si->si_value.sival_int);
    timer_irq = (long)si->si_value.sival_int;
    switch (timer_irq)
    {
    case 1:
        rhythm_timer_handler();
        break;
    case 2:
        UrlRequest_timer_handler();
    default:
        break;
    }
}

void rhythm_timer_handler()
{
    int ret = 0;
    ret = task_rEC();
    if (ret == 0)
    {
        task_gEP();
    }
    else if (ret == -1)
    {
        ;
    }
    else if (ret == -2)
    {
        rhythm_groupOff();
    }
    log_debug("%s called\n", __func__);
}

// 设置节律定时器，5分钟定时一次
#define RHYTHM_TASK_TIME 300
timer_t timerid;
void rhythm_timer_create()
{
    struct sigaction sa;
    // 设置信号处理函数
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = timer_handler;
    sigemptyset(&sa.sa_mask);
    if (sigaction(SIG, &sa, NULL) == -1)
    {
        perror("sigaction");
        exit(EXIT_FAILURE);
    }
    // 创建定时器
    struct sigevent sev;
    sev.sigev_notify = SIGEV_SIGNAL;
    sev.sigev_signo = SIG;
    sev.sigev_value.sival_int = 1;
    if (timer_create(CLOCKID, &sev, &timerid) == -1)
    {
        perror("timer_create");
        exit(EXIT_FAILURE);
    }
    log_info("rhythm timer id:%d", timerid);
}
void rhythm_timer_set()
{
    struct itimerspec its = {{RHYTHM_TASK_TIME, 0}, {1, 0}}; // 定时时间，第一个为间隔时间

    // 设置定时器
    // its.it_value.tv_sec = 1;
    // its.it_value.tv_nsec = 0;
    // its.it_interval.tv_sec = 1;
    // its.it_interval.tv_nsec = 0;
    if (timer_settime(timerid, 0, &its, NULL) == -1)
    {
        perror("timer_settime");
        exit(EXIT_FAILURE);
    }

    // 等待定时器信号
    // while (1)
    // {
    //     sleep(1);
    // }
}

void rhythm_timer_stop()
{
    struct itimerspec its = {{0, 0}, {0, 0}};
    if (timer_settime(timerid, 0, &its, NULL) == -1)
    {
        perror("timer_settime");
        exit(EXIT_FAILURE);
    }
}

void rhythm_stop()
{
    rhythm_timer_stop();
    rhythm_groupOff();
}